ASM 汇编语言 10

  • Created on 2014-11

教材:《汇编语言》(第二版)王爽 著 清华大学出版社

章十三、int 指令

本章介绍 由int指令引发的中断

13.1 int 指令
没有做除法,也可以直接使用 int 0 指令引发除法溢出中断

中断处理程序 —— 简称:中断例程

13.2 编写供应用程序调用的中断例程

实例1:实现2 * 2456^2
使用中断处理程序实现平方
assume cs:code
code segment
start:
     mov ax, cs
     mov ds, ax
     mov si, offset sqr
    
     mov ax, 0
     mov es, ax
     mov di, 200h
    
     mov cx, offset sqrend - offset sqr
     cld
     rep movsb
    
     mov ax, 0
     mov es, ax
     mov word ptr es:[4 * 7ch], 200h
     mov word ptr es:[4 * 7ch + 2], 0
    
     ;test sqr
     mov ax, 3456
     int 7ch
     add ax, ax
     adc dx, dx
    
     mov ax, 4c00h
     int 21h
    
sqr:
     mul ax
     iret
sqrend:
     nop

code ends
end start


实例2:将一个全是字母,以0结尾的字符串,转化为大写。
把终端程序当作子程序来使用。
assume cs:code, ds:data
data segment
     db 'conversion', 0
data ends

code segment
start:
     ;install int 7ch
     mov ax, cs
     mov ds, ax
     mov si, offset capital
    
     mov ax, 0
     mov es, ax
     mov di, 200h
    
     mov cx, offset cap_end - offset capital
     cld
     rep movsb
    
     ;set int 7ch
     mov word ptr es:[4 * 7ch], 200h
     mov word ptr es:[4 * 7ch + 2], 0
    
     ;test int 7ch
     mov ax, data
     mov ds, ax
     mov si, 0
    
     int 7ch
    
     mov ax, 4c00h
     int 21h
    
capital:
     ;暂存寄存器
     pushf
     push cx
    
     mov ch, 0
r0:
     mov cl, ds:[si]
     jcxz ok
    
     cmp cl, 61h
     jb next
     cmp cl, 7ah
     ja next
    
     and byte ptr ds:[si], 11011111b

next:
     inc si
     jmp r0

ok:
     ;恢复寄存器
     pop cx
     popf
    
     iret
    
cap_end:
     nop
code ends
end start


13.3 对int、iret 和 栈的深入理解
目的:用7ch中断例程实现loop指令的功能
实例:在屏幕中间显示80个感叹号“”。
assume cs:code
code segment
start:
     ;install
     mov ax, cs
     mov ds, ax
     mov si, offset lop
    
     mov ax, 0
     mov es, ax
     mov di, 200h
    
     mov cx, offset lop_end - offset lop
     cld
     rep movsb
    
     mov word ptr es:[4 * 7ch], 200h
     mov word ptr es:[4 * 7ch + 2], 0

     ;test
     mov ax, 0b800h
     mov es, ax
     mov di, 12 * 160
    
     mov bx, offset s - offset se
     mov cx, 80
s:
     mov byte ptr es:[di], '!'
     inc di
     inc di
     int 7ch
     ;loop s
se:
     nop
    
     mov ax, 4c00h
     int 21h

lop:
     dec cx     ;想想这句可置于jcxz后吗?
     jcxz ed
    
     ;暂存寄存器
     push bp
    
     mov bp, sp
     add ss:[bp + 2], bx
    
     ;恢复寄存器
     pop bp

ed:
     iret
    
lop_end:
     nop

code ends
end start


13.14 BIOS 和 DOS 所提供的中断例程
在系统板的ROM中存放着一套程序,
称为 BIOS(基础输入输出系统),
主要包含以下几部分内容:
(1)硬件系统的监测和初始化程序
(2)外部中断(15章中详解)和内部中断的中断例程
(3)用于对硬件设备进行I/O操作的中断例程
(4)其它和硬件系统相关的中断例程

从OS(操作系统)的角度看,
DOS的中断例程 就是 OS向coder提供的编程资源。

BIOS和DOS在所提供的中断例程提供了
许多实现了程序员在编程时所需功能的子程序
可以用 int 指令直接调用它们。

和硬件设备相关的DOS中断例程中,
一般都调用了BIOS的中断例程。


13.5 BIOS 和 DOS 中断例程安装过程:
(1)开机,CPU加电,初始化(CS)=0FFFFH,(IP)=0。
自动从FFFF:0单元执行程序,此处有一条跳转指令,
然后将跳转BIOS中硬件系统检测初始化程序

(2)初始化程序建立BIOS所支持的中断变量,
即将BIOS提供的中断例程的入口地址登记在中断向量表中。
*. 注意:对于BIOS所提供的中断例程,
只需将入口地址登记入中断向量表即可,
因为它们具体程序已被固化在ROM中,在内存中一直存在。

(3)硬件系统检测和初始化完成后,
调用 int 19h 进行操作系统引导
自此计算机交给操作系统控制。

(4)DOS启动后,除完成其它工作外,
还将它所提供的中断例程装入内存,并建立相应的中断向量。



13.6 BIOS 中断例程应用(例子)
 int 10h 中断例程是 BIOS 提供的
其中包含多个和屏幕输出相关子程序

一般,供程序员调用的中断例程往往包括多个子程序,
其内部用传递进来的参数决定执行哪个子程序
都用 ah 来传递内部子程序编号

assume cs:code
code segment
start:
     ;指使用 int 10h 中断例程的2号子程序——
     ;置光标
     mov ah, 2
    
     mov bh, 0     ;第0页,bh:页号
     mov dh, 5     ;第5行,dh:行号
     mov dl, 12     ;第12列,dl:列号
    
     int 10h     ;调用10h号中断例程
    
     ;int 10h 9号子程序——
     ;在光标位置显示字符
     mov ah, 9
    
     mov al, 'a'     ;al:显示的字符
     mov bl, 7     ;bl:颜色属性
     mov bh, 0     ;bh:第0页
     mov cx, 3     ;cx:字符重复个数
    
     int 10h
    
     mov ax, 4c00h
     int 21h

code ends
end start

显示缓冲区分为8页,每页4KB,显示器可以显示任一页内容。
一般,显示第0页,即是内存B8000H~B8F9FH的内容。

关于显示缓冲区,详细参考:Assembly Language - Note 6 文末的图



13.7 DOS 中断例程的应用
int 21h 中断例程是 DOS 提供的,其中包含了供程序员编程时调用的子程序。

之前的程序一直以以下语句结尾:
mov ax, 4c00h
int 21h
使用的是 int 21h 中断例程4ch 号子程序
功能程序返回,可提供返回值作为参数。

mov ah, 4ch     ;4ch号子程序,功能:程序返回
mov al, 0     ;al——返回值
int 21h

int 21h 的 9 号子程序 —— 在光标位置显示字符串
ds:dx ;指向字符串,要显示的字符串需用“$”作为结束符
mov ah, 9
int 21h

(完整程序)
assume cs:code
data segment
     db 'Welcome to masm!', '$'
data ends
code segment
start:
     mov ah, 2     ;置光标
     mov bh, 0     ;第0页
     mov dh, 5     ;第5行
     mov dl, 12     ;第12列
     int 10h
    
     mov ax, data
     mov ds, ax
     mov dx, 0
     mov ah, 9
     int 21h
    
     mov ax, 4c00h
     int 21h
code ends
end start



实验13 编写、应用中断例程

(1)编写并安装 int 7ch中断例程,
          功能为显示一个用0结束的字符串,
          中断例程安装在0:200处。
参数:(dh)=行号,(dl)=列号,
          (cl)=颜色,ds:si指向字符串首地址

assume cs:code
data segment
     db 'Welcome to masm!', 0
data ends
code segment
start:
     ;install
     mov ax, cs
     mov ds, ax
     mov si, offset show_str
    
     mov ax, 0
     mov es, ax
     mov di, 200h
    
     mov cx, offset show_end - offset show_str
     cld
     rep movsb
    
     mov word ptr es:[4 * 7ch], 200h
     mov word ptr es:[4 * 7ch + 2], 0
    
     ;test
     mov dh, 10     ;row
     mov dl, 10  ;col
     mov cl, 15     ;color
    
     mov ax, data
     mov ds, ax
     mov si, 0
    
     int 7ch

     mov ax, 4c00h
     int 21h
    
show_str:
     ;暂存寄存器
     push ax
     push di
     push es
    
     mov ax, 0b800h
     mov es, ax
    
     mov al, 80 * 2
     mul dh
     add al, dl     ;ax + dl * 2
     adc ah, 0
     add al, dl
     adc ah, 0
    
     mov di, ax
    
     mov ch, cl
r0:
     cmp byte ptr ds:[si], 0
     je ok
    
     mov cl, ds:[si]     ;此时 ch & cl = color & char
     mov es:[di], cx     ;此时 es:[di] 内存 为 char & color
     ;在寄存器cx中,低字节的char,放在了内存的低地址中
     ;即8086CPU是小端模式的
    
     inc     si
     inc di
     inc di
     jmp r0

ok:
     ;恢复寄存器
     pop es
     pop di
     pop ax
    
     iret
show_end:
     nop
code ends
end start



(2)编写并安装 int 7ch 中断例程,功能为完成loop指令的功能
参数:(cx)=循环次数,(bx)=位移
实现:在屏幕中间显示80个 “”感叹号。

assume cs:code
code segment
start:
     ;install
     mov ax, cs
     mov ds, ax
     mov si, offset lop
    
     mov ax, 0
     mov es, ax
     mov di, 200h
    
     mov cx, offset lop_end - offset lop
     cld
     rep movsb
    
     mov word ptr es:[4 * 7ch], 200h
     mov word ptr es:[4 * 7ch + 2], 0
    
     ;test
     mov ax, 0b800h
     mov es, ax
     mov di, 12 * 160
    
     mov bx, offset r0 - offset r0_end
     mov cx, 80
r0:
     mov byte ptr es:[di], '!'
     inc di
     inc di
     int 7ch
r0_end:
     nop
    
     mov ax, 4c00h
     int 21h
    
lop:
     dec cx
     jcxz ok
    
     push ax
     push bp
    
     ;因为sp不是基址寄存器之一,
     ;不能靠直接写ss:[sp]来操作它
     ;才让sp传值给bp,用ss:[bp + n]……

     mov bp, sp
     mov ax, ss:4[bp]
     add ax, bx
     mov ss:4[bp], ax
    
     pop bp
     pop ax
    
ok:
     iret
lop_end:
     nop

code ends
end start



(3)下面的程序,分别在屏幕的第2、4、6、8行
     显示4句英文诗,补全程序:

assume cs:code
code segment
s1:     db 'Good,better,bset,', '$'
s2:     db 'Never let it rest,', '$'
s3:     db 'Till good is better,', '$'
s4: db 'And better,best.', '$'
s:     dw offset s1, offset s2, offset s3, offset s4
row:     db 2, 4, 6, 8

start:
     mov ax, cs
     mov ds, ax
     mov bx, offset s
     mov si, offset row
     mov cx, 4
    
ok:
     ;int 10h中断例程的2号子程序,置光标
     ;bh:页号
     ;dh:行号
     ;dl:列号
     mov dh, ds:[si]
     mov dl, 0
     mov ah, 2
     int 10h
    
     ;int 21h的9号子程序,在光标位置显示字符串
     ;ds:dx 指向字符串,要显示的字符串需用“$”作为结束符

     mov dx, ds:[bx]
     mov ah, 9
     int 21h
    
     inc si
     add bx, 2

    
     loop ok
    
     mov ax, 4c00h
     int 21h
code ends
end start

0%